package org.social.module;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.bean.AccountInfo;
import org.bean.FriendInfo;
import org.bean.PlayerInfo;
import org.error.GameErrorCode;
import org.social.comparable.PlayerLevelComparable;
import org.social.db.bean.PlayerMap;
import org.social.db.cache.PlayerMapCache;
import org.social.log.RoleRegisterLog;
import org.utils.RemoteUtil;

import com.google.common.collect.Maps;
import com.sojoys.artifact.exception.AbstractLogicModelException;
import com.sojoys.artifact.tools.ToolError;

/**
 * @author : DengYing
 * @CreateDate : 2017年12月6日 下午3:38:27
 * @Description ：Please describe this document
 */
public class PlayerManager {
	private PlayerManager() {
	}

	private static PlayerManager ME = new PlayerManager();

	public static PlayerManager me() {
		return ME;
	}

	/**
	 * 创建一个新的玩家
	 * @param serverId
	 * @return
	 */
	public void createPlayerMap(AccountInfo accountInfo,PlayerInfo playerInfo) {
		synchronized (ME) {
			PlayerMap playerMap = new PlayerMap(0,playerInfo.getUid(), playerInfo.getPid(),playerInfo.getServerId(), Maps.newHashMap());
			playerMap.getPlayerMapProxy().fill(playerInfo);
			playerMap.insert();			
		}
		// 记录注册日志
		RoleRegisterLog.me().log(playerInfo.getUid(), playerInfo.getPid(), accountInfo.getChannelId(),accountInfo.getChannelAppId(), playerInfo.getServerId(), accountInfo.getImei(), accountInfo.getDevice(), accountInfo.getOsType(), accountInfo.getOsVersion());
	}
	
	public PlayerInfo getPlayerInfo(int pid) throws AbstractLogicModelException {
		PlayerMap playerMap = PlayerMapCache.me().getByPid(pid);
		ToolError.isAndTrue(GameErrorCode.NOR_FONT_PLAYERINFO, playerMap == null);
		return playerMap.getPlayerMapProxy().toPlayerInfo();
	}

	/**
	 * 修改玩家信息
	 * @param pid
	 * @param map
	 * @throws AbstractLogicModelException
	 */
	public void changePlayerInfo(int pid,String serverId, Map<Integer, Object> map) throws AbstractLogicModelException {
		PlayerMap playerMap = PlayerMapCache.me().getByPid(pid);
		if (playerMap == null) {
			// 重新远程获取
			PlayerInfo playerInfo = RemoteUtil.gameSync(serverId).getPlayerInfo(pid);
			if (playerInfo!=null) {
				synchronized (ME) {
					playerMap = PlayerMapCache.me().getByPid(pid);
					if (playerMap==null) {
						playerMap = new PlayerMap(0,playerInfo.getUid(), playerInfo.getPid(),playerInfo.getServerId(), Maps.newHashMap());
						playerMap.getPlayerMapProxy().fill(playerInfo);
						playerMap.insert();
					}
				}
			}else {
				return;				
			}
		}
		// 查看是否修改在线状态
		Boolean online = (Boolean) map.remove(PlayerInfo.ONLINE);
		if (online != null) {
			if (online) {
				// 上线进入聊天室
				ChatManager.me().enterChatRoom(pid,0,0);
			} else {
				// 下线退出聊天室
				ChatManager.me().exitChatRoom(pid);				
			}
			playerMap.getPlayerMapProxy().setOnline(online);
		}
		// 修改玩家信息
		playerMap.getInfo().putAll(map);
		playerMap.update();
		
		
		// 通知好友信息变更
		FriendManager.me().notifyFriends(playerMap);
		
		// 如果在线状态 || 等级信息改变。就修改等级排序器
		if (online != null || map.containsKey(PlayerInfo.LVL)) {
			PlayerLevelComparable.putCachne(playerMap);
		}
	}
	

	public Map<Integer, PlayerInfo> getHelpPlayers(int pid, int count, List<Integer> filterPids) {

		String record = PlayerLevelComparable.getRecordByPid(pid);

		String[] contents = record.split("-");

		final int stepSize = 5;

		int nowLvl = Integer.valueOf(contents[0]);

		int lastLvl = nowLvl;

		Map<Integer, PlayerInfo> screenResult = Maps.newLinkedHashMap();
		// 是否筛选完毕
		boolean screenFinish = false;
		Set<Integer> friendsPid = getFriendsPid(pid);

		filterPids.addAll(friendsPid);
		// 先取等级大于自己的
		do {
			int maxlvl = Math.min(PlayerLevelComparable.getMaxLvl(), (lastLvl + stepSize));
			for (int i = maxlvl; i > lastLvl; i--) {
				if (!screenFinish) {
					screenFinish = screenPlayerInfo(filterPids, screenResult,
							PlayerLevelComparable.getPids(i, true, filterPids), count);
				}
				if (!screenFinish) {
					screenFinish = screenPlayerInfo(filterPids, screenResult,
							PlayerLevelComparable.getPids(i, false, filterPids), count);
				}
				if (screenFinish) {
					break;
				}
			}
			lastLvl = maxlvl;
		} while (lastLvl < PlayerLevelComparable.getMaxLvl());

		// 再取等级小于自己的
		lastLvl = nowLvl;
		do {
			int minlvl = Math.max(PlayerLevelComparable.getMinLvl(), (lastLvl - stepSize));
			for (int i = lastLvl; i >= minlvl; i--) {
				if (!screenFinish) {
					screenFinish = screenPlayerInfo(filterPids, screenResult,
							PlayerLevelComparable.getPids(i, true, filterPids), count);
				}
				if (!screenFinish) {
					screenFinish = screenPlayerInfo(filterPids, screenResult,
							PlayerLevelComparable.getPids(i, false, filterPids), count);
				}
				if (screenFinish) {
					break;
				}
			}
			lastLvl = minlvl;
			if (screenFinish) {
				break;
			}
		} while (lastLvl > PlayerLevelComparable.getMinLvl());

		//加入好友信息

		screenPlayerInfo(null,screenResult, friendsPid,count+friendsPid.size());

		return screenResult;
	}

	private Set<Integer> getFriendsPid(Integer pid){
		List<FriendInfo> list = FriendManager.me().getFriends(pid);
		return list.stream()
				.filter(friendInfo -> friendInfo.getStatus() == 1)
				.map(friendInfo -> friendInfo.getPid())
				.collect(Collectors.toSet());
	}

	private boolean screenPlayerInfo(List<Integer> filterPids, Map<Integer, PlayerInfo> screenResult, Set<Integer> pids,
			int count) {
		boolean finish = false;
		if (pids.isEmpty()) {
			return finish;
		}
		for (Integer pid : pids) {
			if (filterPids != null && filterPids.contains(pid)) {
				continue;
			}
			if (screenResult.size() >= count) {
				finish = true;
				break;
			}
			PlayerMap playerMap = PlayerMapCache.me().getByPid(pid);
			if (playerMap == null) {
				continue;
			}
			screenResult.put(pid, playerMap.getPlayerMapProxy().toPlayerInfo());
		}
		return finish;
	}

}
